﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.StaticFiles;
using System.ComponentModel;
using System.IO;

namespace XxSystem.FileManager.core
{
    [DisplayName("本地存储")]
    public class PhyFileService : IFileService
    {
        private readonly string name;
        private readonly string rootPath = "";
        
        public PhyFileService(string name, string rootPath)
        {
            this.name = name;
            this.rootPath = rootPath;
        }
        public void Copy(string sourcePath, string taragetPath)
        {
            var source = getTruePath(sourcePath);
            if (!System.IO.File.Exists(source))
            {
                throw new BizException("文件不存在");
            }
            var target = getTruePath(taragetPath);
            if (System.IO.File.Exists(target))
            {
                throw new BizException("目标文件已经存在");
            }
            var targetDir = Path.GetDirectoryName(target);
            if (!Directory.Exists(targetDir))
            {
                Directory.CreateDirectory(targetDir);
            }
            System.IO.File.Copy(source, target);
        }

        public void CreteDir(string path)
        {
            var truePath = getTruePath(path);
            if (Directory.Exists(truePath)) 
            {
                return;
            }
            Directory.CreateDirectory(truePath);
        }

        public void Delete(string path)
        {
            var addrUrl = getTruePath(path);
            if (!System.IO.File.Exists(addrUrl))
            {
                throw new BizException("文件不存在");
            }
            File.Delete(addrUrl);
        }
 
        public IEnumerable<XFileInfo> GetList(string dir)
        {
            var path = getTruePath(dir ?? "");
            var dirs = Directory.GetDirectories(path);

            foreach (var dirItem in dirs)
            {
                var dirInfo = new DirectoryInfo(dirItem);
                if ((dirInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
                {
                    continue;
                }
                yield return new XFileInfo()
                {
                    Name = dirInfo.Name,
                    FullName = replacePathSepChar(dirInfo.FullName.Replace(rootPath, "")),
                    LastUpdate = dirInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"),
                    IsDir = true
                };
            }
            var files = Directory.GetFiles(path);
            foreach (var fileItem in files)
            {
                var fileInfo = new FileInfo(fileItem);
                if ((fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
                {
                    continue;
                }
                yield return new XFileInfo()
                {
                    Name = fileInfo.Name,
                    FullName = replacePathSepChar(fileInfo.FullName.Replace(rootPath, "")),
                    LastUpdate = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"),
                    Size = fileInfo.Length,
                    Ext = fileInfo.Extension.Replace(".", ""),
                };
            }
        }

        public void Move(string sourcePath, string taragetPath)
        {
            var source = getTruePath(sourcePath);
            if (!System.IO.File.Exists(source))
            {
                throw new BizException("文件不存在");
            }
            var target = getTruePath(taragetPath);
            if (System.IO.File.Exists(target))
            {
                throw new BizException("目标文件已经存在");
            }
            var targetDir = Path.GetDirectoryName(target);
            if (!Directory.Exists(targetDir))
            {
                Directory.CreateDirectory(targetDir);
            }
            System.IO.File.Move(source, target);
        }

        public void MoveDir(string sourcePath, string targetPath)
        {
            var trueTargetPath = getTruePath(targetPath);
            if (Directory.Exists(trueTargetPath)) 
            {
                throw new BizException("目标文件夹已经存在");
            }
            var trueSourcePath = getTruePath(sourcePath);
            Directory.Move(trueSourcePath, trueTargetPath);
        }

        public FileDataInfo Read(string path)
        {
            var addrUrl = getTruePath(path);
            if (!System.IO.File.Exists(addrUrl))
            {
                throw new BizException("文件不存在");
            }
            var stream = System.IO.File.OpenRead(addrUrl);
            string fileExt = Path.GetExtension(addrUrl);
            //获取文件的ContentType
            var provider = new FileExtensionContentTypeProvider();
            var memi = "";
            if (provider.Mappings.ContainsKey(fileExt))
            {
                memi = provider.Mappings[fileExt];
            }
            if (string.IsNullOrEmpty(memi))
            {
                memi = "application/octet-stream";
            }
            return new FileDataInfo() { DataStream= stream,ContentType= memi, FileName = Path.GetFileName(addrUrl) };
        }

        public void RmDir(string path)
        {
            var filePath = getTruePath(path);
            if (!Directory.Exists(filePath))
            {
                throw new BizException("目标文件夹不存在");
            }
            Directory.Delete(filePath, true);
        }

        public async Task Write(string path, Stream stream)
        {
            var filePath = getTruePath(path);
            var fileDir = Path.GetDirectoryName(filePath)??"";
            if (!Directory.Exists(fileDir))
            {
                Directory.CreateDirectory(fileDir);
            }            

            using (var targetStream = System.IO.File.Create(filePath))
            {
                await stream.CopyToAsync(targetStream);
            }
        }

        private string getTruePath(string path) 
        {
            return Path.Combine(rootPath, replacePathTrueSepChar(path));
        }

        private string replacePathSepChar(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return path;
            }
            if (Path.DirectorySeparatorChar == '\\')
            {
                path = path.Replace(Path.DirectorySeparatorChar, '/');
            }
            return path;

        }
        private string replacePathTrueSepChar(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return path;
            }
            if (Path.DirectorySeparatorChar == '\\')
            {
                path = path.Replace('/', Path.DirectorySeparatorChar);
            }
            return path;

        }
    }
}
